package game.square;

import game.dungeon.position.Direction;
import game.square.temperature.Temperature;
import game.square.temperature.TemperatureScale;

import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Set;

import be.kuleuven.cs.som.annotate.Basic;
import be.kuleuven.cs.som.annotate.Raw;

/**
 * A class of Rocks used as a special type of square.
 * 
 * @version 1.0
 * @author Chris Desomer, Geert Heyman
 */

public class Rock extends SquareImpl {


	/**
	 * Initialize this new rock.
	 * 
	 * @param	slipperyMaterial
	 * 			Indicates if this rock is made out of slippery material or not.
	 * @effect	..
	 * 		  | super(slipperyMaterial, false)
	 * @post	..
	 * 		  | For each direction in Direction.values()
	 * 		  |		getBorderInDirection(direction) == Wall
	 */
	@Raw
	public Rock(boolean slipperyMaterial){
		super(slipperyMaterial,	false);
		addWallInAllDirections();	
	}

	/**
	 * Return the temperature of this rock.
	 * 
	 * @return	The temperature of this rock as the average of the temperature of the
	 * 			neighbors of this rock that are no rocks themselves.
	 */
	@Override
	public Temperature getTemperature() {
		Temperature temperature = new Temperature(0, -270, 100000, TemperatureScale.CELCIUS);
		int nbNeighbours = 0;
		for (Direction direction : Direction.values()){
			Square neighbor = getNeighborInDirection(direction);
			if (!(neighbor instanceof Rock) && neighbor != null){
				temperature = temperature.add(neighbor.getTemperature());
				nbNeighbours ++;
			}
		}
		int newTemp = Math.round(temperature.getTemperatureValue(TemperatureScale.CELCIUS)/nbNeighbours);
		temperature.setTemperatureValue(newTemp, TemperatureScale.CELCIUS);
		return temperature;
	}


	/**
	 * Do nothing, because the temperature of a rock is the average of the
	 * temperatures of the surrounding squares.
	 */
	@Override
	public void setTemperature(Temperature temperature){
		
	}

	/*
	 * Add walls in all directions.
	 */
	private void addWallInAllDirections() {
		for (Direction direction : Direction.values())
			addBorderInDirection(new Wall(false), direction);
	}
	
	/**
	 * Return the humidity of this Rock
	 */
	@Override
	@Basic
	public BigDecimal getHumidity(){
		return BigDecimal.ZERO;
	}

	/**
	 * Check if this Rock can have the given humidity, as its
	 * humidity.
	 * 
	 * @param	humidity
	 * 			The humidity to check.
	 * @return	..
	 * 		  |	if (humidity.equals(BigDecimal.ZERO))
	 * 		  |		result == true
	 * @result	..
	 * 		  |	else 
	 * 		  |  	result == false
	 */
	@Override
	public boolean canHaveAsHumidity(BigDecimal humidity) {
		if (humidity.equals(BigDecimal.ZERO))
			return true;
		return false;
	}

	/**
	 * Check if this Rock can have the given border as one of 
	 * its borders
	 * 
	 * @param	border
	 * 			The border to check.
	 * @return	..
	 * 		  | if (!super.canHaveAsBorder(border))
	 * 		  |		then result == false
	 * @result	..
	 * 		  | else if (!(border instanceof Wall))
	 * 		  |		then result == false
	 * @result	..
	 * 		  |	else result == true
	 */
	@Override
	public boolean canHaveAsBorder(Border border) {
		if (!super.canHaveAsBorder(border))
			return false;
		if (!(border instanceof Wall))
			return false;
		return true;
				
	}
	
	/**
	 * Check if this rock has proper borders.
	 * 
	 * @return	..
	 * 		  | if (!super.hasProperBorders())
	 * 		  |		then result == false
	 * @result 	Otherwise, false if and only if in at least one
	 * 			direction the border is no wall. 
	 */
	@Override
	public boolean hasProperBorders() {
		if (!super.hasProperBorders())
			return false;
		for (Direction direction : Direction.values())
			if (!(getBorderInDirection(direction) instanceof Wall))
				return false;
		return true;
	}

	/**
	 * Return the room of this rock, this is a set that only contains
	 * this rock.
	 */
	@Basic
	@Override
	public Set<? extends Square> getRoom() {
		Set<Rock> room = new HashSet<Rock>();
		room.add(this);
		return room;
	}
	
	/**
	 * Check if this rock can reach the given square;
	 * 
	 * @param	square
	 * 			The square to check.
	 * @result	True if and only if the given square is this
	 * 			rock.
	 */
	@Override
	public boolean canReachSquare(Square square) {
		return square == this;
	}

}
